using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;

/// <summary>
/// 场景物件配置信息的Inspector扩展
/// </summary>
[CustomEditor(typeof(SceneObjectsCleanTool))]
public class SceneObjectsCleanToolEditor : Editor
{
    /// <summary>
    /// 第一层的数组
    /// </summary>
    public List<ParentInformation> parentInformations;
    
    /// <summary>
    /// ListView的引用
    /// </summary>
    private ListView listview;
    
    /// <summary>
    /// 找到被扩展的脚本实例
    /// </summary>
    private SceneObjectsCleanTool sceneObjectsCleanTool;

    private void OnEnable()
    {
        sceneObjectsCleanTool = target as SceneObjectsCleanTool;
    }

    /// <summary>
    /// 根节点
    /// </summary>
    private VisualElement root;
    
    public override VisualElement CreateInspectorGUI()
    {
        root = new VisualElement();
        // 被扩展的Inspector信息
        var parentList = new VisualElement();
        InspectorElement.FillDefaultInspector(parentList,serializedObject,this);
        root.Add(parentList);
        
        // Instantiate UXML
        VisualElement visualTreeAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/Inspector/SceneObjectsCleanToolEditor.uxml").CloneTree();
        root.Add(visualTreeAsset);

        // 找到Button 并绑定事件
        Button search = root.Q<Button>("search");
        Button set = root.Q<Button>("set");
        Button reset = root.Q<Button>("reset");
        search.clicked += OnclickSearch;
        set.clicked += OnclickSet;
        reset.clicked += OnclickReset;

        //Listview 并绑定事件
        listview = root.Q<ListView>("ListView"); 
        listview.makeItem += MakeItem;
        listview.bindItem += BindItem;
        
        return root;
    }

    private VisualElement MakeItem()
    {
        VisualElement foldout = new Foldout();
        return foldout;
    }

    private void BindItem(VisualElement element, int index)
    {
        Foldout foldout = element.Q<Foldout>();
        foldout.text = sceneObjectsCleanTool.lists[parentInformations[index].parentIndex].name;
        List<PrefabClass> prefabClasses = parentInformations[index].PrefabClasses;
        Toggle toggle;
        for (int i = 0; i < prefabClasses.Count; i++)
        {
            // 实例化Toggle 绑定Prefab类和数量信息
            toggle = new Toggle();
            string s = "Prefab的类型名称为：" + prefabClasses[i].prefab.name + "  数量为：" + prefabClasses[i].gameobjectLists.Count;
            toggle.text = s;
            toggle.value = true;
            foldout.Add(toggle);
        }
    }

    /// <summary>
    /// 搜索父物体列表中存在的Prefab
    /// </summary>
    private void OnclickSearch()
    {
        Debug.Log("OnclickSearch");
        // 得到父物体列表
        List<GameObject> parentList = sceneObjectsCleanTool.lists;
        // 第一层数组集合 实例化父物体信息列表
        parentInformations = new List<ParentInformation>(parentList.Count);
        
        // 得到子物体列表
        Transform[] childs;
        ParentInformation parentInformation;
        // 根据prefab类型找到对应的PrefabClass 用于辅助
        Dictionary<GameObject, PrefabClass> dictionary;
        for (int i = 0; i < parentList.Count; i++)
        {
            // Debug.Log("Search Parent : " + searchList[i].name);

            // 获取子物体的数量
            int childCount = parentList[i].transform.childCount;
            // 创建数组来存储子物体的 Transform
            childs = new Transform[childCount];
            Debug.Log("+++++++______   " + childs.Length);
            // 循环遍历每个子物体，并将其 Transform 存储在数组中
            for (int p = 0; p < childCount; p++)
            {
                childs[p] = parentList[i].transform.GetChild(p);
            }
            
            // childs = parentList[i].GetComponentsInChildren<Transform>();
            Debug.Log(childs.Length);
            foreach (var VARIABLE in childs)
            {
                Debug.Log(VARIABLE.name);
            }
            parentInformation = new ParentInformation();
            parentInformation.parentIndex = i;//第0个是父物体
            parentInformation.PrefabClasses = new List<PrefabClass>();
            parentInformations.Add(parentInformation);
            
            dictionary = new Dictionary<GameObject, PrefabClass>();

            GameObject prefabRes;
            for (int j = 0; j < childs.Length; j++)
            {
                prefabRes = GetPrefabInfomation(childs[j].gameObject);
                if(prefabRes)//如果是Prefab
                {
                    PrefabClass prefabClass;
                    //1 如果存在PrefabClass 往数组加东西
                    if (dictionary.ContainsKey(prefabRes))
                    {
                        prefabClass = dictionary[prefabRes];

                    }
                    //2 如果没有 新建一个PrefabClass 往数组加东西
                    else
                    {
                        prefabClass = new PrefabClass();
                        prefabClass.gameobjectLists = new List<GameObjectInfomation>();
                        dictionary.Add(prefabRes,prefabClass);
                        parentInformation.PrefabClasses.Add(prefabClass);
                    }
                    
                    //3 往PrefabClass的数组中添加信息
                    prefabClass.prefab = prefabRes;
                    GameObjectInfomation gameObjectInfomation = new GameObjectInfomation();
                    gameObjectInfomation.rotation = childs[j].localRotation.eulerAngles;
                    gameObjectInfomation.position = childs[j].localPosition;
                    gameObjectInfomation.scale = childs[j].localScale;
                    gameObjectInfomation.layer = childs[j].gameObject.layer;
                    prefabClass.gameobjectLists.Add(gameObjectInfomation);
                }
            }
        }
        
        //将数据展示在list上
        listview.itemsSource = sceneObjectsCleanTool.lists;
        listview.Rebuild();
        
        Debug.Log("End Search");
    }
    
    /// <summary>
    /// 保存搜索结果，并将场景中的Gameobject删除
    /// </summary>
    private void OnclickSet()
    {
        Debug.Log("OnclickSet");
        // DebugParentInformations();
        
        //1 根据选择的Prefab整理数据
        var foldouts = root.Query<Foldout>().ToList();
        
        List<PrefabClass> prefabClasses;
        for (int i = 1; i < foldouts.Count; i++)
        {
            // Debug.Log(foldouts[i].text);
            prefabClasses = parentInformations[i-1].PrefabClasses;
            var toggles = foldouts[i].Query<Toggle>().ToList();
            for (int j = toggles.Count - 1; j >= 1 ; j--)
            {
                // Debug.Log(prefabClasses[j-1].prefab.name);
                // Debug.Log(toggles[j].text);
                if (!toggles[j].value)
                {
                    // Debug.Log(prefabClasses[j-1].prefab.name + " is deleted");
                    prefabClasses.RemoveAt(j-1);
                }
                else
                {
                    //2 删除被选择的Prefab
                    DeleteByPrefab(sceneObjectsCleanTool.lists[i - 1], prefabClasses[j - 1].prefab);
                }
            }
        }
        
        //3 将数据存储到ScriptObject中
        string filepath = root.Q<TextField>("filepath").value;
        string filename = root.Q<TextField>("filename").value;
        
        SceneInformation sceneInformation = ScriptableObject.CreateInstance<SceneInformation>();
        sceneInformation.lists = parentInformations;
        sceneInformation.sceneIndex = SceneManager.GetActiveScene().buildIndex;
        AssetDatabase.CreateAsset(sceneInformation,
            filepath + filename + sceneInformation.sceneIndex +".asset");
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        
        // 将生成的ScriptObject文件绑定到脚本上
        sceneObjectsCleanTool.sceneInformation = sceneInformation;
        
        // 将搜索结果置空
        listview.itemsSource = null;
        listview.Rebuild();
        Debug.Log("End OnclickSet");
    }

    /// <summary>
    /// 根据选择需要被收集的物件类型 删除GameObjects
    /// 根据Prefab的类型 删除Prefab
    /// </summary>
    /// <param name="parent">prefab所在的父物体对象</param>
    /// <param name="prefab">prefab的引用</param>
    private void DeleteByPrefab(GameObject parent, GameObject prefab)
    {
        // 获取子物体的数量
        int childCount = parent.transform.childCount;
        // 创建数组来存储子物体的 Transform
        Transform[] gameObjects = new Transform[childCount];
        // 循环遍历每个子物体，并将其 Transform 存储在数组中
        for (int p = 0; p < childCount; p++)
        {
            gameObjects[p] = parent.transform.GetChild(p);
        }
        for (int i = 0; i < gameObjects.Length; i++)
        {
            if (prefab == GetPrefabInfomation(gameObjects[i].gameObject))
            {
                DestroyImmediate(gameObjects[i].gameObject);
            }
        }
    }

    /// <summary>
    /// 将ScriptObject中的信息还原到场景中
    /// </summary>
    private void OnclickReset()
    {
        Debug.Log("OnclickReset");
        SceneInformation sceneInformation = sceneObjectsCleanTool.sceneInformation;//得到配置信息
        List<GameObject> parents = sceneObjectsCleanTool.lists;//得到父物体列表
        
        List<ParentInformation> lists = sceneInformation.lists;
        if (lists == null) return;
        for (int i = 0; i < lists.Count; i++)
        {
            ParentInformation parentInformation = lists[i];
            GameObject parent = parents[parentInformation.parentIndex];
            List<PrefabClass> PrefabClasses = parentInformation.PrefabClasses;
            for (int j = 0; j < PrefabClasses.Count; j++)
            {
                GameObject prefab = PrefabClasses[j].prefab;

                for (int k = 0; k < PrefabClasses[j].gameobjectLists.Count; k++)
                {
                    GameObject go = PrefabUtility.InstantiatePrefab(prefab,SceneManager.GetActiveScene()) as GameObject;
                    go.transform.SetParent(parent.transform);
                    go.transform.localPosition = PrefabClasses[j].gameobjectLists[k].position;
                    go.transform.localRotation = Quaternion.Euler(PrefabClasses[j].gameobjectLists[k].rotation);
                    go.transform.localScale = PrefabClasses[j].gameobjectLists[k].scale;
                    go.layer = PrefabClasses[j].gameobjectLists[k].layer;
                }
            }
        }
        Debug.Log("End OnclickReset");
    }
    
    /// <summary>
    /// 检查是否为prefab 如果是返回prefab的引用，否则返回null
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    private GameObject GetPrefabInfomation(GameObject obj)
    {
        if (obj == null)
        {
            Debug.LogError("GameObjects are null.");
            return null;
        }

        PrefabInstanceStatus prefabType = PrefabUtility.GetPrefabInstanceStatus(obj);

        if (prefabType!= PrefabInstanceStatus.NotAPrefab)
        {
            GameObject prefabObj = PrefabUtility.GetCorrespondingObjectFromOriginalSource(obj);
            return prefabObj;
        }
        return null;
    }
    
    /// <summary>
    /// 用于Debug
    /// 打印parentInformations中的信息
    /// </summary>
    private void DebugParentInformations()
    {
        foreach (var v1 in parentInformations)
        {
            GameObject parentGo =  sceneObjectsCleanTool.lists[v1.parentIndex];
            Debug.Log(parentGo.name + "****************");
            foreach (var v2 in v1.PrefabClasses)
            {
                Debug.Log(v2.prefab.name + "——————————————————————————————————");
                foreach (var v3 in v2.gameobjectLists)
                {
                    Debug.Log(v3.position);
                    Debug.Log(v3.rotation);
                    Debug.Log(v3.scale);
                    Debug.Log(v3.layer);
                    // GameObject gameObject = Instantiate(v2.prefab, v3.position, Quaternion.Euler(v3.rotation));
                    // gameObject.transform.localScale = v3.scale;
                    // gameObject.layer = v3.layer;
                }
                Debug.Log(v2.prefab.name + "——————————————————————————————————");
            }
            Debug.Log(parentGo.name + "****************");
        }
    }
}
